#include "tcp_server.h"

#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"

#include "esp_err.h"
#include "esp_log.h"

#include <sys/socket.h>
#include <netinet/in.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <inttypes.h>

static const char *TAG = "TCP_SERVER";

/* 全局变量 */
static int server_sock = -1;
static TaskHandle_t tcp_server_task_handle = NULL;
static tcp_recv_callback_t user_recv_cb = NULL;
static void *user_cb_arg = NULL;
static bool tcp_server_running = false;

/* 客户端链表，用于管理所有已连接的客户端 */
typedef struct tcp_client {
    int fd;
    TaskHandle_t task_handle;
    struct tcp_client *next;
} tcp_client_t;

static tcp_client_t *client_list = NULL;
static SemaphoreHandle_t client_list_mutex = NULL;

/* --- 内部函数 --- */

/**
 * @brief 将新客户端添加到客户端链表中
 */
static void add_client(int client_fd, TaskHandle_t task_handle)
{
    tcp_client_t *client = malloc(sizeof(tcp_client_t));
    if (!client) {
        ESP_LOGE(TAG, "分配客户端内存失败");
        return;
    }
    client->fd = client_fd;
    client->task_handle = task_handle;
    client->next = NULL;

    xSemaphoreTake(client_list_mutex, portMAX_DELAY);
    client->next = client_list;
    client_list = client;
    xSemaphoreGive(client_list_mutex);
}

/**
 * @brief 从客户端链表中移除指定客户端
 */
static void remove_client(int client_fd)
{
    xSemaphoreTake(client_list_mutex, portMAX_DELAY);
    tcp_client_t *prev = NULL;
    tcp_client_t *cur = client_list;
    while (cur) {
        if (cur->fd == client_fd) {
            if (prev) {
                prev->next = cur->next;
            } else {
                client_list = cur->next;
            }
            free(cur);
            break;
        }
        prev = cur;
        cur = cur->next;
    }
    xSemaphoreGive(client_list_mutex);
}

/**
 * @brief 处理单个客户端连接的任务
 */
static void tcp_client_task(void *pvParameters)
{
    int client_fd = (int)(intptr_t)pvParameters;
    ESP_LOGI(TAG, "客户端 %d 已连接", client_fd);

    char buffer[128];
    while (tcp_server_running) {
        int len = recv(client_fd, buffer, sizeof(buffer), 0);
        if (len > 0) {
            if (user_recv_cb) {
                user_recv_cb(client_fd, (uint8_t *)buffer, len, user_cb_arg);
            }
        } else if (len == 0) {
            ESP_LOGI(TAG, "客户端 %d 已断开连接", client_fd);
            break;
        } else {
            ESP_LOGE(TAG, "客户端 %d recv 错误: errno %d", client_fd, errno);
            break;
        }
    }
    remove_client(client_fd);
    close(client_fd);
    ESP_LOGI(TAG, "客户端任务 %d 退出", client_fd);
    vTaskDelete(NULL);
}

/**
 * @brief TCP 服务器主任务，负责监听并接收新的客户端连接
 */
static void tcp_server_task(void *pvParameters)
{
    /* pvParameters 为传入的监听端口，调用后释放 */
    uint16_t port = *(uint16_t *)pvParameters;
    free(pvParameters);

    struct sockaddr_in server_addr;
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(port);
    server_addr.sin_addr.s_addr = INADDR_ANY;

    server_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
    if (server_sock < 0) {
        ESP_LOGE(TAG, "创建 socket 失败: errno %d", errno);
        goto EXIT;
    }

    int opt = 1;
    if (setsockopt(server_sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0) {
        ESP_LOGE(TAG, "setsockopt 错误: errno %d", errno);
        goto EXIT;
    }

    if (bind(server_sock, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
        ESP_LOGE(TAG, "绑定 socket 失败: errno %d", errno);
        goto EXIT;
    }

    if (listen(server_sock, 5) < 0) {
        ESP_LOGE(TAG, "listen 错误: errno %d", errno);
        goto EXIT;
    }

    ESP_LOGI(TAG, "TCP 服务器在端口 %d 监听", port);

    while (tcp_server_running) {
        struct sockaddr_in client_addr;
        uint32_t addr_len = sizeof(client_addr);
        int client_fd = accept(server_sock, (struct sockaddr *)&client_addr, &addr_len);
        if (client_fd < 0) {
            if (tcp_server_running) {
                ESP_LOGE(TAG, "accept 失败: errno %d", errno);
            }
            break;
        }

        TaskHandle_t client_task_handle = NULL;
        if (xTaskCreate(tcp_client_task, "tcp_client_task", 4096, (void *)(intptr_t)client_fd, 5, &client_task_handle) == pdPASS) {
            add_client(client_fd, client_task_handle);
        } else {
            ESP_LOGE(TAG, "创建客户端任务失败");
            close(client_fd);
        }
    }

EXIT:
    tcp_server_running = false;
    if (server_sock != -1) {
        close(server_sock);
        server_sock = -1;
    }
    ESP_LOGI(TAG, "TCP 服务器任务退出");
    vTaskDelete(NULL);
}

/* --- 对外接口 --- */

esp_err_t tcp_server_start(uint16_t port, tcp_recv_callback_t recv_cb, void *cb_arg)
{
    if (tcp_server_running) {
        ESP_LOGW(TAG, "TCP 服务器已在运行");
        return ESP_ERR_INVALID_STATE;
    }

    user_recv_cb = recv_cb;
    user_cb_arg = cb_arg;
    tcp_server_running = true;

    if (client_list_mutex == NULL) {
        client_list_mutex = xSemaphoreCreateMutex();
        if (client_list_mutex == NULL) {
            ESP_LOGE(TAG, "创建客户端互斥锁失败");
            return ESP_FAIL;
        }
    }

    /* 为任务参数动态分配内存 */
    uint16_t *p_port = malloc(sizeof(uint16_t));
    if (!p_port) {
        ESP_LOGE(TAG, "分配内存失败");
        tcp_server_running = false;
        return ESP_FAIL;
    }
    *p_port = port;

    if (xTaskCreate(tcp_server_task, "tcp_server_task", 4096, p_port, 5, &tcp_server_task_handle) != pdPASS) {
        ESP_LOGE(TAG, "创建 TCP 服务器任务失败");
        free(p_port);
        tcp_server_running = false;
        return ESP_FAIL;
    }

    return ESP_OK;
}

esp_err_t tcp_server_stop(void)
{
    if (!tcp_server_running) {
        return ESP_ERR_INVALID_STATE;
    }

    tcp_server_running = false;
    if (server_sock != -1) {
        close(server_sock);
        server_sock = -1;
    }

    /* 遍历并关闭所有客户端 */
    xSemaphoreTake(client_list_mutex, portMAX_DELAY);
    tcp_client_t *client = client_list;
    while (client) {
        close(client->fd);
        client = client->next;
    }
    xSemaphoreGive(client_list_mutex);

    if (tcp_server_task_handle) {
        vTaskDelete(tcp_server_task_handle);
        tcp_server_task_handle = NULL;
    }
    ESP_LOGI(TAG, "TCP 服务器已停止");
    return ESP_OK;
}

esp_err_t tcp_server_send(int client_fd, const uint8_t *data, size_t len)
{
    if (client_fd < 0) {
        return ESP_ERR_INVALID_STATE;
    }
    int ret = send(client_fd, data, len, 0);
    if (ret < 0) {
        ESP_LOGE(TAG, "向客户端 %d 发送数据失败: errno %d", client_fd, errno);
        return ESP_FAIL;
    }
    return ESP_OK;
}

esp_err_t tcp_server_broadcast(const uint8_t *data, size_t len)
{
    esp_err_t ret_val = ESP_OK;
    xSemaphoreTake(client_list_mutex, portMAX_DELAY);
    tcp_client_t *client = client_list;
    while (client) {
        int ret = send(client->fd, data, len, 0);
        if (ret < 0) {
            ESP_LOGE(TAG, "向客户端 %d 广播数据失败: errno %d", client->fd, errno);
            ret_val = ESP_FAIL;
        }
        client = client->next;
    }
    xSemaphoreGive(client_list_mutex);
    return ret_val;
}

int tcp_server_get_fd(void)
{
    return client_list->fd;
}
